import * as THREE from './three.module.js'
// import { CSS3DRenderer, CSS3DObject } from './CSS3DRenderer.js'
// import { OBJLoader } from './OBJLoader.js'
// import { MTLLoader } from './MTLLoader.js'
import { STLLoader } from './STLLoader.js'
import { TrackballControls } from './TrackballControls.js'
import {TWEEN} from './tween.module.min.js'
// import { OutlineEffect } from './OutlineEffect.js'
// import { RectAreaLightUniformsLib } from './RectAreaLightUniformsLib.js'

// 基于jquery,three.js
// 为特定流程显示做的简单sdk
window.zr3d = function(dom_id,objInfo,frustumSize){
    this.getUUID = function(){
        var temp_url = URL.createObjectURL(new Blob())
        var uuid = temp_url.toString()
        URL.revokeObjectURL(temp_url)
        return uuid.substr(uuid.lastIndexOf("/") + 1)
    }
    // 给绑定事件的自身的唯一ID
    this.uu_id = this.getUUID()
    // 左右一半宽度
    this.frustumSize = frustumSize || 30
    // 加载模型给的后台数据信息(模型参数)
    this.objInfo = objInfo
    this.dom_id = dom_id
    this.jdom = $(`#${dom_id}`)
    this.camera = ''
    this.scene = ''
    this.model = ''
    this.controls = ''
    this.renderer = ''
    this.task_animate = ''
    this.tween = ''
    this.autoRote = false
    this.showEdges = 'un'
    this.init()
    // 默认定义一些材质
    this.defaultMeraList={
        // 黄铜材质
        brass:{
            color: 0xff7f1a,
            // specular:0xcea189,
            metalness: 0.8,
            roughness: 0.5,
            // envMap: textureCube,
            // flatShading: true
        }
    }
}
zr3d.prototype = {
    constructor:zr3d,
    init:function(){
        // 给dom初始化按钮组示例
        this.init_button()
        // 初始化相机
        this.init_camera()
        this.init_scene()
        this.scene.add(this.camera)
        this.init_render()
        this.init_controls()
        // 动画执行
        this.task_animate = this.animate
        this.animate(this)()
        // 加载模型
        this.STLloadModel()
    },
    init_button(){
        let _this = this
        this.jdom.css('position','relative')
        this.jdom.append(`
            <div class="${this.uu_id}" style="display: flex;position: absolute;bottom: 0;width: 100%;left: 0;height: 50px;background-color:#e3e3e3">
                <div class="zr-3d-button hock-auto-rote" data-type='auto_route'>自动旋转</div>
                <div class="zr-3d-button hock-front" data-type='front'>正视图</div>
                <div class="zr-3d-button hock-left" data-type='left'>侧视图</div>
                <div class="zr-3d-button hock-top" data-type='top'>顶视图</div>
                <div class="zr-3d-button hock-line-m" data-type='model'>模</div>
                <div class="zr-3d-button hock-line-l" data-type='line'>框</div>
                <div class="zr-3d-button hock-line-ml" data-type='modelline'>模+框</div>
            </div>
        `)
        // 绑定事件
        $(`.${this.uu_id} .zr-3d-button`).on('click',function(e){
            let position = $(this).attr('data-type')
            _this[`click_${position}`]()
        })
    },
    move_camera_position(oldP, newP){
        let _this = this
        var tween = new TWEEN.Tween(oldP)
        tween.to(newP,500)
        tween.easing(TWEEN.Easing.Cubic.InOut)
        tween.start()
        tween.onUpdate(()=>{
            _this.camera.position.set(oldP.x,oldP.y,oldP.z)
        })
    },
    move_camera_up(oldUp,newUp){
        let _this = this
        var tweenUp = new TWEEN.Tween(oldUp)
        tweenUp.to(newUp,500)
        tweenUp.easing(TWEEN.Easing.Cubic.InOut)
        tweenUp.start()
        tweenUp.onUpdate(()=>{
            _this.camera.up.x = oldUp.x
            _this.camera.up.y = oldUp.y
            _this.camera.up.z = oldUp.z
        })
    },
    move_camera_zoom(oldZoom,newZoom){
        let _this = this
        var tweenZoom = new TWEEN.Tween(oldZoom)
        tweenZoom.to(newZoom,500)
        tweenZoom.easing(TWEEN.Easing.Cubic.InOut)
        tweenZoom.start()
        tweenZoom.onUpdate(()=>{
            _this.camera.zoom = oldZoom.zoom
            _this.camera.updateProjectionMatrix()
        })
    },
    move_controls(oldC,newC){
        let _this = this
        var tweenC = new TWEEN.Tween(oldC)
        tweenC.to(newC,500)
        tweenC.easing(TWEEN.Easing.Cubic.InOut)
        tweenC.start()
        tweenC.onUpdate(()=>{
            _this.controls.target.x = oldC.x
            _this.controls.target.y = oldC.y
            _this.controls.target.z = oldC.z
        })
    },
    init_camera(){
        let aspect = this.jdom.width() / this.jdom.height()
        this.camera = new THREE.OrthographicCamera( this.frustumSize * aspect * -1, this.frustumSize * aspect, this.frustumSize, -this.frustumSize, 1, 5000 );
        let pointLight = new THREE.PointLight( 0xffffff,1 )
        this.camera.add(pointLight)
        this.camera.position.set( 1000,1000, 1000 )
        this.camera.up.x=0
        this.camera.up.y=1
        this.camera.up.z=0
    },
    init_scene(){
        this.scene = new THREE.Scene()
        this.scene.background = new THREE.TextureLoader().load('/js/zr/img/bg.jpg')
        var ambient = new THREE.AmbientLight( 0xffffff, 2 );
        this.scene.add( ambient )
    },
    init_render(){
        // 默认渲染模式
        this.renderer = new THREE.WebGLRenderer()
        this.renderer.setPixelRatio(window.devicePixelRatio)
        this.renderer.setSize(this.jdom.width(), this.jdom.height())
        this.jdom[0].appendChild(this.renderer.domElement)
        this.render()
    },
    init_controls(){
        this.controls = new TrackballControls( this.camera, this.renderer.domElement )
        // 旋转速度
        this.controls.rotateSpeed = 20.0
        // 缩放速度
        this.controls.zoomSpeed = 2
        // 平移速度
        // this.controls.noPan = false
        this.controls.panSpeed = 1
        // 最小视角
        this.controls.minDistance = 0
        // 最大视角
        this.controls.maxDistance = Infinity
        // 无惯性移动
        this.controls.staticMoving = true
    },
    OBJloadModel(){
        let _this = this
        let loader = new OBJLoader( );
        loader.load( this.objInfo.model_url, function ( obj ) {
            _this.model = obj
            var material = new THREE.MeshPhysicalMaterial({
                color: 0x444444,
                // specular:0xffffff, // 反光色
                // shininess:3, // 反光亮度
                // transparent: true, // 是否开启透明
                // opacity:1, //透明度
                // overdraw:true, // 过度描绘
                // wireframe:true, // 渲染成线框模式
            })
            _this.model.children[0].material = material
            _this.scene.add( _this.model )
            _this.render()
        }, ()=>{}, ()=>{} );
    },
    STLloadModel(){
        let _this = this
        let loader = new STLLoader( );
        loader.load( this.objInfo.model_url, function ( obj ) {
            var material = new THREE.MeshPhysicalMaterial(_this.defaultMeraList[_this.objInfo.mer])
            // 重设物体中心
            obj.computeBoundingBox() // 这个对重设不影响,但是能计算包围盒的顶点,留着备查
            obj.center()
            var mesh = new THREE.Mesh(obj, material);
            _this.model = mesh
            _this.scene.add(mesh)
            _this.render()
            // 加载模型边框
            var edges = new THREE.EdgesHelper( _this.model, 0x000000 );//设置边框，可以旋转
            _this.edges = edges
        }, ()=>{}, ()=>{} );
    },
    animate(self){
        // 此处因为requestAnimationFrame是全局方法,下一次this指向就变了
        // 做个闭包,每次把this指向带进去
        return ()=>{
            requestAnimationFrame( self.animate(self) )
            self.controls.update()
            self.render()
        }
    },
    render(){
        TWEEN.update()
        this.camera.lookAt( this.scene.position )
        if(this.controls){
            this.controls.update()
        }
        if(this.autoRote){
            // 该方法为参考鼠标移动内部实现的自定义方法,需要把该方法拷贝进源码
            // 由于方法内部使用的是闭包,也无法通过外部方式扩展
            this.controls.zrRoute()
        }
        this.renderer.render( this.scene, this.camera )
    },
}

// 自动旋转
zr3d.prototype.click_auto_route = function(){
    this.move_controls(this.controls.target,{x:0,y:0,z:0})
    this.autoRote = !this.autoRote
    // 自动旋转时禁止平移,否则会出问题
    this.controls.noPan = this.autoRote
    // 改变文字
    $(`.${this.uu_id} .hock-auto-rote`).html(this.autoRote?'停止旋转':'自动旋转')
}

// 正视图
zr3d.prototype.click_front = function(){
    this.move_camera_position(this.camera.position,{x:0,y:0,z:2000})
    this.move_camera_up(this.camera.up,{x:0,y:1,z:0})
    this.move_camera_zoom({zoom:this.camera.zoom},{zoom:1})
    this.move_controls(this.controls.target,{x:0,y:0,z:0})
}

// 侧视图
zr3d.prototype.click_left = function(){
    this.move_camera_position(this.camera.position,{x:2000,y:0,z:0})
    this.move_camera_up(this.camera.up,{x:0,y:1,z:0})
    this.move_camera_zoom({zoom:this.camera.zoom},{zoom:1})
    this.move_controls(this.controls.target,{x:0,y:0,z:0})
}

// 顶视图
zr3d.prototype.click_top = function(){
    this.move_camera_position(this.camera.position,{x:0,y:2000,z:0})
    this.move_camera_up(this.camera.up,{x:0,y:0,z:-1})
    this.move_camera_zoom({zoom:this.camera.zoom},{zoom:1})
    this.move_controls(this.controls.target,{x:0,y:0,z:0})
}

// 底视图
zr3d.prototype.click_bottom = function(){
    this.move_camera_position(this.camera.position,{x:0,y:-2000,z:0})
    this.move_camera_up(this.camera.up,{x:0,y:0,z:1})
    this.move_camera_zoom({zoom:this.camera.zoom},{zoom:1})
    this.move_controls(this.controls.target,{x:0,y:0,z:0})
}

// 模
zr3d.prototype.click_model = function(){
    // 重置模+框
    this.showEdges='show'
    this.click_modelline()
    this.model.material.wireframe = false
    // this.model.material.wireframe = !this.model.material.wireframe
}

// 框
zr3d.prototype.click_line = function(){
    // 重置模+框
    this.showEdges='show'
    this.click_modelline()
    this.model.material.wireframe = true
    // this.model.material.wireframe = !this.model.material.wireframe
}

// 模加框
zr3d.prototype.click_modelline = function(){
    // 重置线框模式
    this.model.material.wireframe = false
    if(this.showEdges=='un'){
        this.showEdges='show'
        this.scene.add( this.edges )
    } else if(this.showEdges=='show'){
        this.showEdges='un'
        this.scene.remove(this.edges)
    }
    this.renderer.enabled = !this.renderer.enabled
    this.render()
}
